package p41_autoconfig;

import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.SimpleCommandLinePropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.type.AnnotationMetadata;

@Configuration
@Import(_3_DataSource相关的自动配置.MyDeferredImportSelector.class)
public class _3_DataSource相关的自动配置 {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        StandardEnvironment env = new StandardEnvironment();
        //在环境里加一些配置项
        env.getPropertySources().addLast(
                new SimpleCommandLinePropertySource(
                        "--spring.datasource.url=jdbc:mysql://localhost:3306/test",
                        "--spring.datasource.username=root",
                        "--spring.datasource.password=220600"
                )
        );
        context.setEnvironment(env);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(context.getDefaultListableBeanFactory());
        context.registerBean(_3_DataSource相关的自动配置.class);
        /**
         * MybatisAutoConfiguration自動配置类会注册一个用于扫描mapper接口(必须加@Mapper注解)的bean:AutoConfiguredMapperScannerRegistrar
         * AutoConfigurationPackages用于记录boot启动类的包名，作为mapper接口的扫描范围
         * @AutoConfigurationPackage注解就是干了这事
         */
        AutoConfigurationPackages.register(context.getDefaultListableBeanFactory(),
                _3_DataSource相关的自动配置.class.getPackageName());
        context.refresh();

        for (String name : context.getBeanDefinitionNames()) {
            //根据bean的来源，过滤掉没有不重要的bean
            if (context.getBeanDefinition(name).getResourceDescription() != null) {
                System.out.println("===>" + name + " -> " + context.getBeanDefinition(name).getResourceDescription());
            }
        }
    }

    static class MyDeferredImportSelector implements DeferredImportSelector {
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {

            return new String[]{
                    //配置数据源的自动配置类(主要添加了名为dataSource的bean)
                    DataSourceAutoConfiguration.class.getName(),
                    //配置mybatis相关bean的自动配置类(主要添加了名为sqlSessionFactory、sqlSessionTemplate的bean)
                    MybatisAutoConfiguration.class.getName(),
                    //配置事务管理器的自动配置类(transactionManager)
                    DataSourceTransactionManagerAutoConfiguration.class.getName(),
                    //声明式的事务管理自动配置类(internalTransactionAdvisor切面、transactionAttributeSource切点、transactionInterceptor通知)
                    TransactionAutoConfiguration.class.getName()
            };
        }
    }
}
